package org.mozhu.learning.algo.binary_search.cases.sqrt;

/**
 * 牛顿迭代法近似求解根号
 * 设r是f(x) = 0的根，选取x0作为r初始近似值，过点（x0,f(x0)）做曲线y = f(x)的切线L，L的方程为y = f(x0)+f'(x0)(x-x0)，求出L与x轴交点的横坐标 x1 = x0-f(x0)/f'(x0)，称x1为r的一次近似值。
 * 过点（x1,f(x1)）做曲线y = f(x)的切线，并求该切线与x轴交点的横坐标 x2 = x1-f(x1)/f'(x1)，称x2为r的二次近似值。重复以上过程，得r的近似值序列，其中x(n+1)=x(n)－f(x(n))/f'(x(n))，称为r的n+1次近似值，上式称为牛顿迭代公式。
 * 根据牛顿迭代的原理，可以得到以下的迭代公式：X(n+1)=[X(n)+p/X(n)]/2
 * 或者这么解释：
 * 1. 对x的平方根的值一个猜想y。
 * 2. 通过执行一个简单的操作去得到一个更好的猜测：只需要求出y和x/y的平均值（它更接近实际的平方根值）。
 */
public class NewtonSqrt implements Sqrt {

    @Override
    public double sqrt(double number, double precision) {
        double sqrt = 1.0;
        while (abs(sqrt * sqrt - number) > precision) {
            sqrt = (sqrt + number / sqrt) / 2;
            System.out.println(sqrt);
        }
        return sqrt;
    }

    private double abs(double v) {
        return v >= 0 ? v : v * -1;
    }
}
